#include "SweepLine.h"
#include "main.h"
#include "bintree.h"
#include <string> 

class SweepLine;
void get_intersections( vector<SLseg*> segmenty, set<Point*> *outp)
{
    EventQueue  Eq(segmenty);
    SweepLine * SL = new SweepLine ();
    Event*      e;						//aktualny event
    SLseg*      s;						//aktualny segment sweepline-u

	//prejdeme doradu vsetky eventy, je to bud lavy vrchol, pravy vrchol alebo priesecnik
    while (e = Eq.next()) 
	{        
        switch (e->type)
		{
			case LEFT: 
				{     
					//pridaj do sweeplajny
				     s = SL->add(e);         
					 if (s)
					 {
						 if (s->above) SL->intersect(s->above, s, &Eq);
						 if (s->below) SL->intersect(s, s->below, &Eq);						 
					 }
					 break;
				 }				
			case RIGHT: 
				{
					//odober zo sweeplajny
				     s = SL->find(e);
					 if(s) 
					 {
						 SLseg* tempa;
						 SLseg* tempb;
						 tempa = s->above;
						 tempb = s->below;
						 SL->remove(s);
						 if (tempa && tempb) SL->intersect(tempa, tempb, &Eq);
					 }
					 break;
				}			
			case INTERSECTION:
				{
					outp->insert(e->eV);
					
					//v bode kde sa pretnu sa vymenia navzajom upper a lower
					SLseg* tmp = e->intersectUpper->above;					
					e->intersectUpper->above = e->intersectLower;
					e->intersectLower->above = tmp;
					e->intersectUpper->below = e->intersectLower->below;
					e->intersectLower->below = e->intersectUpper;
					tmp = NULL;

					//pre nove usporiadanie segmentov skus pretnut prilahne s.
					SL->intersect(e->intersectLower->above, e->intersectLower, &Eq);
					SL->intersect(e->intersectUpper->below, e->intersectUpper, &Eq);
				}
        }
    }
}
///<summary>
///pouzite pri nacitavani, vytvori z riadku v tvare "w x y z" segment s bodmi v tomto poradi
///povazuje % a # za komentare a ignoruje tieto riadky
///</summary>
SLseg* vytvor_segment(string s)
{
	float temp_x1 = 0, temp_y1 = 0, temp_x2 = 0, temp_y2 = 0;

	int l_zarazka = 0;
	int l_zarazka1 = s.find(" ",0);

	bool chyba = false;

	if ((s[0] == '%') || (s[0] == '#')) chyba = true;

	chyba |= from_string(temp_x1, s.substr(l_zarazka, l_zarazka1), dec);
	l_zarazka = l_zarazka1+1;
	l_zarazka1 = s.find(" ",l_zarazka+1);
	
	chyba |= from_string(temp_y1, s.substr(l_zarazka, l_zarazka1), dec);
	l_zarazka = l_zarazka1+1;
	l_zarazka1 = s.find(" ",l_zarazka+1);
	
	chyba |= from_string(temp_x2, s.substr(l_zarazka, l_zarazka1), dec);
	l_zarazka = l_zarazka1+1;
	l_zarazka1 = s.find(" ",l_zarazka+1);

	chyba |= from_string(temp_y2, s.substr(l_zarazka), dec);

	if (chyba) 
	{
		return (SLseg*)0;
	}
	else
	{
		return new SLseg(new Point(temp_x1, temp_y1), new Point(temp_x2, temp_y2));
	}
}


///<summary>
/// *****entry point
///</summary>
int main(int argc, char* argv[])
{
	//upravit arg
	argc--; argv++;
	//ak mame malo parametrov vypis usage
	if (argc < 2)
	{
		cout << "Pouzitie: sweepline <input_file> <output_file>" << endl;
		cout << "<input_file> vo formate \"x1 y1 x2 y2\\n...\"" << endl;
		return 1;
	}

	static set<Point*> outpoints;
	vector<SLseg*> segmenty;
	string line;
	line.clear();
	segmenty.clear();
	outpoints.clear();

	ifstream infile (argv[0], ios_base::in);
	//sanity check
	if (!infile.is_open())
	{
		printf ("Chyba pri otvarani vstupneho suboru!");
		return 1;
	}

	SLseg* temp_seg;
	int i = 0;
	while (getline(infile, line, '\n'))
	{
		if(temp_seg = vytvor_segment(line))
		{
			temp_seg->edge = i++;
			segmenty.push_back(temp_seg);
		}
		else { /*ignore*/ }
	}
	infile.close();
#ifdef DEBUG
	cout << "Uspesne nacitanych segmentov: " << segmenty.size() << endl;
#endif
	//do outpoints prirad vsetky priesecniky medzi segmentami
	get_intersections(segmenty, &outpoints);

	set<Point*>::iterator it;

	ofstream outfile (argv[1], ios_base::out);
	//sanity check
	if (!outfile.is_open())
	{
		printf ("Chyba pri otvarani vystupneho suboru!");
		return 1;
	}
	try{
	//zapis vsetky body do suboru
	for(it = outpoints.begin(); it != outpoints.end();)
	{		
		outfile << (*it)->ToString();
		it++;		
	}
	}catch(char *){;}
	cout << "Zapisanych intersekci: " << outpoints.size() << endl;
	outfile.close();
}
